Layouts 在設計網頁時扮演重要的角色,提供共用的介面以保持多個頁面有一致的外觀與結構。<NuxtLayout>
如果沒有指定 name
,預設會使用 layouts/default.vue
。使用方式為利用 <slot />
來挖洞存放頁面的內容,當然也可以根據需求自定義多個不同的佈局。今天就來介紹如何有效的運用 Nuxt 3 的 Layouts。
建立 layout
// layouts/default.vue
<template>
<div>
<h1>default layout</h1>
<slot />
</div>
</template>
使用 <NuxtLayout>
元件
// app.vue
<template>
<NuxtLayout> my contents </NuxtLayout>
</template>
layouts/default.vue
的 <slot />
就是 app.vue
的 <NuxtLayout>
內包裹元素的顯示位置,此處 "my contents" 可以換成 <NuxtPage />
,將畫面設定為 /pages
對應的頁面。app.vue
定義就好。<slot />
,以確保在頁面切換、佈局更改時自動應用過渡效果(Transition)。除了 layouts/default.vue
外,須使用其他佈局。
佈局名稱標準為 kebab-case,如果檔名為 creativePlanet.vue
,則 layout
名稱會是 creative-planet
。
建立 custom
layout
// layouts/custom.vue
<template>
<div>
<h1>custom layout</h1>
<slot />
</div>
</template>
需指定 <NuxtLayout>
的 name
,若無指定則會是 layouts/default.vue
。
name
直接傳字串(name="要使用的佈局檔案名稱"
)
// app.vue
<template>
<NuxtLayout name="custom"> my contents </NuxtLayout>
</template>
name
用 v-bind
的方式綁定
// app.vue
<template>
<NuxtLayout :name="layout"> my contents </NuxtLayout>
</template>
<script setup lang="ts">
const layout = "custom";
</script>
利用 definePageMeta()
覆蓋預設佈局
// app.vue - 佈局為 layouts/default.vue
<template>
<NuxtLayout> <NuxtPage/> </NuxtLayout>
</template>
// pages/index.vue - 佈局覆蓋為 layouts/custom.vue
<template>
my contents
</template>
<script setup lang="ts">
definePageMeta({
layout: 'custom'
})
</script>
nuxt devtools 查看 /
的 layout
改為 custom ,其他頁面則會是(default)。
⚠ 注意:definePageMeta()
是用來設定頁面的 utils,因此只能在頁面元件(通常位於 pages/
目錄下,也可以在 nuxt.config.ts
設定其他路徑)的 <script>
或 <script setup>
使用。如果嘗試在不符合上述條件的地方使用,將會失效並出現警告訊息:
definePageMeta() is a compiler-hint helper that is only usable inside the script block of a single file component which is also a page. Its arguments should be compiled away and passing it at runtime has no effect.
這意味著因為不符合上述條件,definePageMeta()
在執行時不會有任何效果。
Layouts 中可以插入自訂的具名 Slots,讓佈局有分區塊需求時,能更加靈活運用。
建立具名的 slot 並設定預設內容。
// layouts/custom.vue
<template>
<div>
<h1>custom layout</h1>
<h2><slot name="header"> default header content. </slot></h2>
<main>
<slot />
</main>
</div>
</template>
使用時指定相對應的 slot 名稱,沒有指定的內容則會放在 <main>
區塊內。
// app.vue
<template>
<NuxtLayout name="custom">
<template #header> Some header template cotent. </template>
The rest of the page.
</NuxtLayout>
</template>
<NuxtLink>
應用將多個頁面共用 Layout,並且可以在佈局內加上 <NuxtLink>
讓使用者能更輕鬆的切換頁面。
目前 layouts/
及 pages/
資料結構
nuxt-project
┣ layouts
┃ ┣ custom.vue
┃ ┗ default.vue
┣ pages
┃ ┣ index.vue
┃ ┣ about.vue
┃ ┗ service.vue
增加 <NuxtLink>
// layouts/custom.vue
<template>
<div>
<div>
<div>Welcome to CreativePlanet !</div>
<NuxtLink to="/">Home</NuxtLink>
<NuxtLink to="/about">Who we are</NuxtLink>
<NuxtLink to="/service">What we do</NuxtLink>
</div>
<slot />
</div>
</template>
直接在 app.vue
使用,統一整個網站的佈局
// app.vue
<template>
<NuxtLayout :name="layout">
<NuxtPage />
</NuxtLayout>
</template>
<script setup lang="ts">
const layout = "custom";
</script>
// pages/index.vue
<template>
<div>
<h1>Welcome to CreativePlanet !</h1>
<button @click="EnableCustomLayout"> Update Layout </button>
</div>
</template>
<script setup lang="ts">
const EnableCustomLayout = () => {
setPageLayout('custom')
}
definePageMeta({
layout: false
})
</script>
definePageMeta({ layout: false })
表示該頁面預設不使用任何佈局,不可用於 app.vue
。setPageLayout()
是 Nuxt 3 提供的 Utils,可用來動態變更頁面的佈局,可用於 app.vue
。如果還沒建立專案的朋友,也可以先嘗試看看官方文件的線上 layouts 範例。
這兩天介紹了 Pages 和 Layouts,明天會介紹 Middleware 的應用。